#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <Assembler.h>
#include <MyFunctions.h>
#include <assert.h>

CMD_Description* Asm(FILE* Input, CMD_Description* Text_Of_The_Program, int Key[]);

CMD_Description* Asm(FILE* Input, CMD_Description* Text_Of_The_Program, int Key[])
{
    Checking_File(Input,"Input.txt");

    char str[Command_Length];
    char *string = NULL;

    int counter = 0;
    
    while (True)
    {
        string = fgets (str, sizeof(str), Input);
        int  Right = False, First = 0, Second = 0;
        char Letter ;


        if (string == NULL)
        {
            if (feof (Input) != 0)
            {
                break;
            }
            else
            {
                printf ("\nReading Error!\n");
                break;
                assert(0);
            }
        }


//--------------------------------------------------------------------------------------------
        if (sscanf (string, "%c%d",&Letter, &First) == 2 && Letter ==':' && Right == False)
        {
            Key[First] = counter + 1;
            counter++;
        }

        if (sscanf (string, "push %d", &First) == 1 && Right == False) //push with NUM
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = PUSH;
            Text_Of_The_Program[counter].Argument_Counter   = 1;
            Text_Of_The_Program[counter].Arguments[0]    = First;
            counter++;
        }

        if (sscanf (string, "pushr %d", &First) == 1 && Right == False)  //push with register
        {
            Right = True;
            Text_Of_The_Program[counter].cmd  = PUSHR;
            Text_Of_The_Program[counter].Argument_Counter   = 1;
            Text_Of_The_Program[counter].Arguments[0]    = First;
            counter++;
        }

        if (sscanf (string, "outr %d", &First) == 1 && Right == False) //out register
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = OUTR;
            Text_Of_The_Program[counter].Argument_Counter   = 1;
            Text_Of_The_Program[counter].Arguments[0]    = First;
            counter++;
        }

        if (sscanf (string, "popr %d", &First) == 1 && Right == False)  //pop from stack
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = POPR;
            Text_Of_The_Program[counter].Argument_Counter   = 1;
            Text_Of_The_Program[counter].Arguments[0]    = First;
            counter++;
        }


        if (sscanf (string, "incr %d", &First) == 1 && Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = INCR;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "jer :%d", &First) == 1 && Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JER;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "jner :%d", &First) == 1 && Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JNER;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }



        if (sscanf (string, "mov r%d r%d", &First, &Second) == 2&& Right == False)   //copy 2nd register to 1st
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = MOV;
            Text_Of_The_Program[counter].Argument_Counter = 2;
            Text_Of_The_Program[counter].Arguments[0] = First;
            Text_Of_The_Program[counter].Arguments[1] = Second;
            counter++;
        }

        if (sscanf (string, "jmp :%d", &First) == 1 && Right == False)              //jump on command (string in file)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JMP;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "ad%c", &Letter) == 1 && Letter == 'd'&& Right == False)       //add 2 last elems in stack
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = ADD;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }

        if (sscanf (string, "su%c", &Letter) == 1 && Letter == 'b'&& Right == False)        //sub 2 last elems in stack
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = SUB;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }

        if (sscanf (string, "mu%c", &Letter) == 1 && Letter == 'l'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = MUL;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }

        if (sscanf (string, "di%c", &Letter) == 1 && Letter == 'v'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = DIV;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }

        if (sscanf (string, "sqr%c", &Letter) == 1 && Letter =='t'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = SQRT;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }


        if (sscanf (string, "j%c :%d", &Letter, &First) == 2 && Letter == 'e'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JE;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "jn%c :%d", &Letter, &First) == 2 && Letter == 'e'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JNE;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }


        if (sscanf (string, "j%c :%d", &Letter, &First) == 2 && Letter == 'a'&& Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = JA;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }


        if (sscanf (string, "j%c :%d", &Letter, &First) == 2 && Letter == 'b'&& Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = JB;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }


        if (sscanf (string, "jn%c :%d", &Letter, &First) == 2 && Letter == 'a'&& Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd  = JNA;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }


        if (sscanf (string, "jn%c :%d", &Letter, &First) == 2 && Letter == 'b'&& Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = JNB;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "call :%d",  &First) == 1 && Right == False)
        {
            Right = True;
            Text_Of_The_Program[counter].cmd = CALL;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "re%c", &Letter) == 1 && Letter =='t'&& Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = RET;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }


        if (sscanf (string, "in %d", &First) == 1 && Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = IN;
            Text_Of_The_Program[counter].Argument_Counter = 1;
            Text_Of_The_Program[counter].Arguments[0] = First;
            counter++;
        }

        if (sscanf (string, "ou%c", &Letter) == 1 && Right == False && Letter == 't')
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = OUT;
            Text_Of_The_Program[counter].Argument_Counter = 0;
            counter++;
        }

        if (sscanf (string, "en%c", &Letter) == 1 && Letter =='d' && Right == False)
        {
            Right  = True;
            Text_Of_The_Program[counter].cmd = END;
            Text_Of_The_Program[counter].Argument_Counter = 0;
        }

        if (Right == False) {};

//--------------------------------------------------------------------------------------------
    }

    fclose(Input);

    Length = counter;


return Text_Of_The_Program;
}


int Write (FILE* Output, CMD_Description* Text_Of_The_Program)
{
    Checking_File(Output,"name");
    int counter = Length;
    int line = 0;
    for (line = 0; line <= counter; line++)

      { if (Text_Of_The_Program[line].Argument_Counter == 0) fprintf(Output, "%d\n", Text_Of_The_Program[line].cmd);
        if (Text_Of_The_Program[line].Argument_Counter == 1) fprintf(Output, "%d %d %d\n", Text_Of_The_Program[line].cmd, Text_Of_The_Program[line].Argument_Counter, Text_Of_The_Program[line].Arguments[0]);
        if (Text_Of_The_Program[line].Argument_Counter == 2) fprintf(Output, "%d %d %d %d\n", Text_Of_The_Program[line].cmd, Text_Of_The_Program[line].Argument_Counter,Text_Of_The_Program[line].Arguments[0],Text_Of_The_Program[line].Arguments[1]);
       }

    fclose (Output);


return 0;
}



int wrbin (FILE* Output, CMD_Description* program)
{
    Output = fopen("assembler_out.bin","wb");
    int counter = Length;
    int line = 0;
    printf("\n %d \n", Length+1);
    for (line = 0; line <= counter; line++)

      { if (program[line].Argument_Counter == 0) fwrite(&program[line].cmd, sizeof(int), 1, Output);
        if (program[line].Argument_Counter == 1)
            {
            fwrite(&program[line].cmd, sizeof(int), 1, Output);
            fwrite(&program[line].Argument_Counter, sizeof(int), 1, Output);
            fwrite(&program[line].Arguments[0], sizeof(int), 1, Output);
            }
        if (program[line].Argument_Counter == 2)
            {
            fwrite(&program[line].cmd, sizeof(int), 1, Output);
            fwrite(&program[line].Argument_Counter, sizeof(int), 1, Output);
            fwrite(&program[line].Arguments,sizeof(int),2,Output);
            }
       }
    fclose (Output);

return 0;
}



/*int main()
{

}*/


